
/*
 *  ThunderCfg.cpp
 *
 *  Crack & combian video file
 *
 *  Create by Peter Liu < peter9882@gmail.com >
 *
 *  Modify by Peter Liu < peter9882@gmail.com >
 *  2010/03/04
 *
 */

#include "StdAfx.h"
#include "ThunderCfg.h"

#define MIN(a, b)   ((a)>(b)?(b):(a))

CThunderCfg::CThunderCfg(void)
: m_URL_Length(0)
, m_Title_Length(0)
, m_Description_Length(0)
, m_Block_A_Count(0)
, m_Block_B_Count(0)
, m_Encrypt_Length(0)
, m_Block_A_Offset(0)
, m_Block_B_Offset(0)
, m_EncryptMethod(0)
, m_CrackArg0(0)
{
    bCfgFileActive = false;

    memset(strUrl, 0, URL_LEN);
    memset(strTitle, 0, TITLE_LEN);
    memset(strDescription, 0, DESCRIPTION_LEN);
    strFileName = _T("");

    strHeadBuffer = (U8 *)malloc(HEAD_BUFFER_LEN);
    strVideoBuffer = (U8 *)malloc(VIDEO_BUFFER_LEN);
}

CThunderCfg::~CThunderCfg(void)
{
    if (strHeadBuffer)
        free(strHeadBuffer);

    if (strVideoBuffer)
        free(strVideoBuffer);
}

ANSI_STRING * CThunderCfg::GetUrl(void)
{
    return (strUrl);
}

ANSI_STRING * CThunderCfg::GetTitle(void)
{
    return (strTitle);
}

ANSI_STRING * CThunderCfg::GetDescription(void)
{
    return (strDescription);
}

U32 CThunderCfg::GetDateTime(void)
{
    return (m_DateTime);
}


bool CThunderCfg::OpenCfgFile(CString fileName)
{
    CFile file;
    U32 fileLen;

    strFileName = fileName;

    bCfgFileActive = false;
    m_Block_A_Count = 0;
    m_Block_B_Count = 0;
    m_Block_A_Offset = 0;
    m_Block_B_Offset = 0;
    m_Encrypt_Length = 0;
    m_Description_Length = 0;
    m_Title_Length = 0;
    m_URL_Length = 0;
    m_DateTime = 0;
    m_Encrypt_Length = 0;



    if (file.Open(strFileName, CFile::modeRead))
    {
        fileLen = file.GetLength();
        if (fileLen > CFG_BUFFER_LEN)
        {
            fileLen = CFG_BUFFER_LEN;
        }

        file.SeekToBegin();
        file.Read(strCfgBuffer, file.GetLength());

        bCfgFileActive = Parse();

        file.Close();
    }

    return (bCfgFileActive);
}

bool CThunderCfg::Parse(void)
{
    U32 *pu32;

    pu32 = (U32 *)strCfgBuffer;
    if (*pu32 != 1)
        return false;

    pu32 ++;
    m_URL_Length = *pu32;
    pu32 ++;
    memcpy(strUrl, pu32, m_URL_Length);
    strUrl[m_URL_Length] = 0;

    pu32 = (U32 *)(((U8 *)pu32) + m_URL_Length);
    m_Title_Length = *pu32;
    pu32 ++;
    memcpy(strTitle, pu32, m_Title_Length);
    strTitle[m_Title_Length] = 0;

    pu32 = (U32 *)(((U8 *)pu32) + m_Title_Length);
    m_Description_Length = *pu32;
    pu32 ++;
    memcpy(strDescription, pu32, m_Description_Length);
    strDescription[m_Description_Length] = 0;

    pu32 = (U32 *)(((U8 *)pu32) + m_Description_Length);
    m_DateTime = *pu32;
    pu32 ++;
    m_Encrypt_Length = *pu32;
    pu32 ++;
    m_Block_A_Count = *pu32;
    pu32 ++;
    m_Block_A_Offset = (U8 *)pu32 - strCfgBuffer;
    pu32 += m_Block_A_Count * BLOCK_A_ITEM_BYTE >> 2;
    m_Block_B_Count = *pu32;
    pu32 ++;
    m_Block_B_Offset = (U8 *)pu32 - strCfgBuffer;

    if ((m_Block_A_Count>0) && (m_Block_A_Count == m_Block_B_Count))
    {
        return (true);
    }

    return (false);
}

U32 CThunderCfg::GetBlockCount(void)
{
    return (m_Block_A_Count);
}

U64 CThunderCfg::GetBlockStartAddr(U32 index)
{
    ST_BLOCK_A *pstBlockA;

    pstBlockA = (ST_BLOCK_A *)(strCfgBuffer + 
        m_Block_A_Offset + index * BLOCK_A_ITEM_BYTE);

    return (pstBlockA->u64Addr);
}

U64 CThunderCfg::GetBlockLength(U32 index)
{
    ST_BLOCK_A *pstBlockA;

    pstBlockA = (ST_BLOCK_A *)(strCfgBuffer + 
        m_Block_A_Offset + index * BLOCK_A_ITEM_BYTE);

    return (pstBlockA->u64Length);
}

U32 CThunderCfg::GetBlockFlag(U32 index)
{
    ST_BLOCK_B *pstBlockB;

    pstBlockB = (ST_BLOCK_B *)(strCfgBuffer + 
        m_Block_B_Offset + index * BLOCK_B_ITEM_BYTE);

    return (pstBlockB->u32Flag);
}

bool CThunderCfg::Save(CString strSrcFolder, CString filename)
{
    if (!bCfgFileActive)
        return false;

    if ((!strHeadBuffer) || (!strVideoBuffer))
        return false;

    CFile fileOpen, fileSave;
    U32 fileLen;

    CString srcFile = strSrcFolder + _T("/0.dat");
    CString str1;

    HWND       g_WindowHandle=((CDialog   *)AfxGetMainWnd())->GetSafeHwnd();   

    if (fileSave.Open(filename, CFile::modeCreate|CFile::modeWrite))
    {
        U32 i, u32Num;
        for (i=0; i<m_Block_A_Count; i++)
        {
            SendMessage(g_WindowHandle, WM_UPDATEDATA, (100 * i / m_Block_A_Count), 0);

            u32Num = GetBlockStartAddr(i);
            str1.Format(_T("/%d.dat"), u32Num);
            srcFile = strSrcFolder + str1;
            fileOpen.Open(srcFile, CFile::modeRead);

            fileLen = GetBlockLength(i);
            fileOpen.SeekToBegin();
            fileOpen.Read(strVideoBuffer, fileLen);
            fileOpen.Close();

            if ((0 == i) || (1 == i) || (m_Block_A_Count-1 == i))
            {
                GetEncryptMethod(strVideoBuffer);
            }
            
            {
                Crack(strVideoBuffer, MIN(m_Encrypt_Length, fileLen));
            }
            
            fileSave.Seek(u32Num, CFile::begin);
            fileSave.Write(strVideoBuffer, fileLen);
        }       
    }

    fileSave.Close();

    return (true);
}

bool CThunderCfg::Crack(U8 * buffer, U32 crackLen)
{
    //U8 *buffer = strHeadBuffer;
    //U32 crackLen = m_Encrypt_Length;

    U32 i;

    if (ENCRYPT_METHOD_1 == m_EncryptMethod)
    {
        for (i=0; i<crackLen; i++)
        {
            *(buffer+i) = *(buffer+i) + m_CrackArg0;
        }

        return (true);
    }

    return false;
}

U32 CThunderCfg::GetEncryptMethod(U8 * buffer)
{
    U8 * n = buffer;
    U8 x;
    m_EncryptMethod = ENCRYPT_METHOD_NONE;
    

    // wmv file 
    //      30 26 b2 75 8e 66
    if ( ((U8)(n[1]+0x0a) == n[0]) && ((U8)(n[1]+0x8c) == n[2]) 
        && ((U8)(n[1]+0x4f) == n[3]) && ((U8)(n[1]+0x68) == n[4]) 
        && ((U8)(n[1]+0x40) == n[5]) )
    {
        x = 0x100 + 0x30 - n[0];
        m_EncryptMethod = ENCRYPT_METHOD_1;
        m_CrackArg0 = x;
    }

    //      82 00 00
    else if ( (n[1] == n[2]) && ((U8)(n[1]+0x82) == n[0]) )
    {
        x = 0x100 - n[1];
        m_EncryptMethod = ENCRYPT_METHOD_1;
        m_CrackArg0 = x;
    }

    //      90 08 00 33
    else if ( (n[0] == (U8)(n[1]+0x88)) 
        && (n[0] == (U8)(n[2]+0x90))
        && (n[0] == (U8)(n[3]+0x5d)))
    {
        x = 0x100 - n[2];
        m_EncryptMethod = ENCRYPT_METHOD_1;
        m_CrackArg0 = x;
    }

    // rmvb file:
    //      .RMF  2E 52 4D 46
    else if (((U8)(n[0]+0x24) == n[1]) 
        && ((U8)(n[0]+0x1f) == n[2])
        && ((U8)(n[0]+0x18) == n[3]))
    {
        x = 0x100 + 0x2e - n[0];
        m_EncryptMethod = ENCRYPT_METHOD_1;
        m_CrackArg0 = x;
    }
    
    //      DATA  44 41 54 41
    else if ((n[1] == n[3]) 
        && ((U8)(n[1]+0x03) == n[0])
        && ((U8)(n[1]+0x13) == n[2]))
    {
        x = 0x100 + 0x44 - n[0];
        m_EncryptMethod = ENCRYPT_METHOD_1;
        m_CrackArg0 = x;
    }

    //      INDX  49 4E 44 58
    else if (((U8)(n[2]+0x05) == n[0])
        && ((U8)(n[2]+0x0a) == n[1])
        && ((U8)(n[2]+0x14) == n[3]))
    {
        x = 0x100 + 0x49 - n[0];
        m_EncryptMethod = ENCRYPT_METHOD_1;
        m_CrackArg0 = x;
    }

    return m_EncryptMethod;
}

